package com.doris.media.picker.utils

import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.text.TextUtils
import android.util.Log
import android.util.Size
import androidx.exifinterface.media.ExifInterface
import com.doris.media.picker.model.MediaColumn
import com.doris.media.picker.model.MediaMimeType
import com.doris.media.picker.model.MediaModel
import com.doris.media.picker.model.MediaPickerConfig
import java.io.File
import java.math.BigDecimal
import java.util.*
import kotlin.concurrent.thread

object MediaUtils {

    private const val tag = "MediaUtils"

    private fun getSelection(mimeType: ArrayList<String>): String {
        val stringBuffer = StringBuffer(MediaColumn.mimeType)
        repeat(mimeType.count() - 1) {
            stringBuffer.append("=? or ")
            stringBuffer.append(MediaColumn.mimeType)
        }
        stringBuffer.append("=?")
        return stringBuffer.toString()
    }

    private fun getSelectionValue(mimeType: ArrayList<String>): String {
        val stringBuffer = StringBuffer()
        mimeType.forEachIndexed { index, s ->
            stringBuffer.append(MediaColumn.mimeType).append("='").append(s).append("'")
            if (index < mimeType.size - 1) {
                stringBuffer.append(" or ")
            }
        }
        return stringBuffer.toString()
    }

    /**
     * 获取第一张图片
     */
    @JvmStatic
    fun firstImage(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.IMAGE_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (MediaModel) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.IMAGE_DEFAULT)
        thread {
            val projection = arrayOf(
                MediaColumn.path, MediaColumn.size, MediaColumn.width, MediaColumn.height
            )
            val selection = if (mimeType.isEmpty()) null else getSelection(mimeType)
            val cursor = context.contentResolver.query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
                selection, mimeType.toTypedArray(), orderBy
            ) ?: return@thread
            val model = MediaModel()
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue
                // 尺寸
                var w = cursor.getInt(2)
                var h = cursor.getInt(3)
                val imageSize = getImageSize(path)
                if (w != imageSize.width || h != imageSize.height) {
                    w = imageSize.width
                    h = imageSize.height
                }
                if (w == 0 || h == 0) continue
                // 数据
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.width = w
                model.height = h
                model.lastModifed = file.lastModified()
                break
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(model) }
        }
    }

    @JvmStatic
    fun firstImageJava(context: Context?, callback: (MediaModel) -> Unit) {
        firstImage(context, callback = callback)
    }

    /**
     * 加载图片
     */
    @JvmStatic
    fun loadImage(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.IMAGE_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.IMAGE_DEFAULT)
        thread {
            val data = ArrayList<MediaModel>()
            val projection = arrayOf(
                MediaColumn.path, MediaColumn.size, MediaColumn.width, MediaColumn.height
            )
            val selection = if (mimeType.isEmpty()) null else getSelection(mimeType)
            val cursor = context.contentResolver.query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
                selection, mimeType.toTypedArray(), orderBy
            ) ?: return@thread
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue
                // 尺寸
                var w = cursor.getInt(2)
                var h = cursor.getInt(3)
                val imageSize = getImageSize(path)
                if (w != imageSize.width || h != imageSize.height) {
                    w = imageSize.width
                    h = imageSize.height
                }
                if (w == 0 || h == 0) continue
                // 数据
                val model = MediaModel()
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.width = w
                model.height = h
                model.lastModifed = file.lastModified()
                data.add(model)
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(data) }
        }
    }

    @JvmStatic
    fun loadImageJava(context: Context?, callback: (ArrayList<MediaModel>) -> Unit) {
        loadImage(context, callback = callback)
    }

    /**
     * 加载图片
     */
    @JvmStatic
    fun loadImage(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.IMAGE_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        pageSize: Int = 24,
        pageIndex: Int = 0,
        startTime: Long = 0,
        endTime: Long = System.currentTimeMillis(),
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.IMAGE_DEFAULT)
        thread {
            val data = ArrayList<MediaModel>()
            val projection = arrayOf(
                MediaColumn.path, MediaColumn.size, MediaColumn.width, MediaColumn.height
            )
            val cursor: Cursor?
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                val queryArgs = Bundle()
                queryArgs.putStringArray(
                    ContentResolver.QUERY_ARG_SORT_COLUMNS,
                    orderBy.replace(" ", "")
                        .replace("desc", "")
                        .replace("asc", "")
                        .split(",").toTypedArray()
                )
                if (orderBy.contains("desc")) {
                    queryArgs.putInt(
                        ContentResolver.QUERY_ARG_SORT_DIRECTION,
                        ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
                    )
                } else {
                    queryArgs.putInt(
                        ContentResolver.QUERY_ARG_SORT_DIRECTION,
                        ContentResolver.QUERY_SORT_DIRECTION_ASCENDING
                    )
                }
                queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, pageSize)
                queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, pageSize * pageIndex)

                val selectionValue = StringBuilder()

                if (mimeType.isNotEmpty()) {
                    val sbMimeType = StringBuilder()
                    mimeType.forEachIndexed { index, s ->
                        if (index > 0) {
                            sbMimeType.append(",")
                        }
                        sbMimeType.append(" '${s}' ")
                    }
                    selectionValue.append(MediaColumn.mimeType)
                        .append(" IN (${sbMimeType})")
                        .append(" AND ")
                }

                selectionValue
                    .append(MediaStore.Images.Media.SIZE)
                    .append(" >= $minSize ")

                if (maxSize > 0) {
                    selectionValue
                        .append(" AND ")
                        .append(MediaStore.Images.Media.SIZE)
                        .append(" <= $maxSize ")
                }

                selectionValue.append(" AND ")
                    .append(MediaStore.Images.Media.DATE_ADDED)
                    .append(" >= ${(startTime / 1000).toInt()}")

                selectionValue.append(" AND ")
                    .append(MediaStore.Images.Media.DATE_ADDED)
                    .append(" <= ${(endTime / 1000).toInt()}")

                Log.d(tag, "----------------------selectionValue:  $selectionValue")

                queryArgs.putString(
                    ContentResolver.QUERY_ARG_SQL_SELECTION,
                    selectionValue.toString()
                )

                cursor = context.contentResolver.query(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    projection, queryArgs, null
                )
            } else {
                val selection = StringBuilder()
                val selectionArgs = arrayListOf<String>()

                if (mimeType.isNotEmpty()) {
                    val sbMimeType = StringBuilder()
                    mimeType.forEachIndexed { index, s ->
                        if (index > 0) {
                            sbMimeType.append(",")
                        }
                        sbMimeType.append("?")
                    }
                    selection.append(MediaColumn.mimeType)
                        .append(" IN (${sbMimeType})")
                        .append(" AND ")
                    selectionArgs.addAll(mimeType.toTypedArray())
                }
                selection
                    .append(MediaStore.Images.Media.SIZE)
                    .append(" >= ? ")
                selectionArgs.add(minSize.toString())

                if (maxSize > 0) {
                    selection
                        .append(" AND ")
                        .append(MediaStore.Images.Media.SIZE)
                        .append(" <= ? ")
                    selectionArgs.add(maxSize.toString())
                }
                selection.append(" AND ")
                    .append(MediaStore.Images.Media.DATE_TAKEN)
                    .append(">= ?")
                selectionArgs.add(startTime.toString())

                selection.append(" AND ")
                    .append(MediaStore.Images.Media.DATE_TAKEN)
                    .append(" <= ?")
                selectionArgs.add(endTime.toString())

                cursor = context.contentResolver.query(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
                    selection.toString(), selectionArgs.toTypedArray(),
                    "$orderBy limit $pageSize offset ${pageSize * pageIndex}"
                )
            }
            if (cursor == null) return@thread
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                /*if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue*/
                // 尺寸
                var w = cursor.getInt(2)
                var h = cursor.getInt(3)
                val imageSize = getImageSize(path)
                if (w != imageSize.width || h != imageSize.height) {
                    w = imageSize.width
                    h = imageSize.height
                }
                if (w == 0 || h == 0) continue
                // 数据
                val model = MediaModel()
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.width = w
                model.height = h
                model.lastModifed = file.lastModified()
                data.add(model)
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(data) }
        }
    }


    @JvmStatic
    fun loadImageJava(
        context: Context?, pageSize: Int, pageIndex: Int,
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        loadImage(context, pageSize = pageSize, pageIndex = pageIndex, callback = callback)
    }

    /**
     * 加载视频
     */
    @JvmStatic
    fun loadVideo(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.VIDEO_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.VIDEO_DEFAULT)
        thread {
            val data = ArrayList<MediaModel>()
            val projection = arrayOf(
                MediaColumn.path, MediaColumn.size, MediaColumn.width, MediaColumn.height,
                MediaColumn.duration
            )
            val selection = if (mimeType.isEmpty()) null else getSelection(mimeType)
            val cursor = context.contentResolver.query(
                MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection,
                selection, mimeType.toTypedArray(), orderBy
            ) ?: return@thread
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue
                // 时长
                val d = cursor.getLong(4)
                if (d <= 1000) continue
                // 尺寸
                var w = cursor.getInt(2)
                var h = cursor.getInt(3)
                if (w == 0 || h == 0) {
                    val videoSize = getVideoSize(path)
                    w = videoSize.width
                    h = videoSize.height
                }
                if (w == 0 || h == 0) continue
                // 数据
                val model = MediaModel()
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.duration = d
                model.durationTransform = transformTime(d)
                model.width = w
                model.height = h
                model.lastModifed = file.lastModified()
                model.type = MediaPickerConfig.TYPE_VIDEO
                data.add(model)
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(data) }
        }
    }

    @JvmStatic
    fun loadVideoJava(context: Context?, callback: (ArrayList<MediaModel>) -> Unit) {
        loadVideo(context, callback = callback)
    }

    @JvmStatic
    fun loadVideo(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.VIDEO_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        pageSize: Int = 24,
        pageIndex: Int = 0,
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.VIDEO_DEFAULT)
        thread {
            val data = ArrayList<MediaModel>()
            val projection = arrayOf(
                MediaColumn.path, MediaColumn.size, MediaColumn.width, MediaColumn.height,
                MediaColumn.duration
            )
            val cursor: Cursor?
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                val queryArgs = Bundle()
                if (orderBy.contains("desc")) {
                    queryArgs.putInt(
                        ContentResolver.QUERY_ARG_SORT_DIRECTION,
                        ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
                    )
                } else {
                    queryArgs.putInt(
                        ContentResolver.QUERY_ARG_SORT_DIRECTION,
                        ContentResolver.QUERY_SORT_DIRECTION_ASCENDING
                    )
                }
                queryArgs.putStringArray(
                    ContentResolver.QUERY_ARG_SORT_COLUMNS,
                    arrayOf(
                        orderBy.replace(" ", "")
                            .replace("desc", "")
                            .replace("asc", "")
                    )
                )
                queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, pageSize)
                queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, pageSize * pageIndex)
                if (mimeType.isNotEmpty())
                    queryArgs.putString(
                        ContentResolver.QUERY_ARG_SQL_SELECTION,
                        getSelectionValue(mimeType)
                    )
                cursor = context.contentResolver.query(
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                    projection, queryArgs, null
                )
            } else {
                val selection = if (mimeType.isEmpty()) null else getSelection(mimeType)
                cursor = context.contentResolver.query(
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection,
                    selection, mimeType.toTypedArray(),
                    "$orderBy limit $pageSize offset ${pageSize * pageIndex}"
                )
            }
            if (cursor == null) return@thread
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue
                // 时长
                val d = cursor.getLong(4)
                if (d <= 1000) continue
                // 尺寸
                var w = cursor.getInt(2)
                var h = cursor.getInt(3)
                if (w == 0 || h == 0) {
                    val videoSize = getVideoSize(path)
                    w = videoSize.width
                    h = videoSize.height
                }
                if (w == 0 || h == 0) continue
                // 数据
                val model = MediaModel()
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.duration = d
                model.durationTransform = transformTime(d)
                model.width = w
                model.height = h
                model.lastModifed = file.lastModified()
                model.type = MediaPickerConfig.TYPE_VIDEO
                data.add(model)
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(data) }
        }
    }

    @JvmStatic
    fun loadVideoJava(
        context: Context?, pageSize: Int, pageIndex: Int,
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        loadVideo(context, pageSize = pageSize, pageIndex = pageIndex, callback = callback)
    }

    /**
     * 加载音频
     */
    @JvmStatic
    fun loadAudio(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.AUDIO_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.AUDIO_DEFAULT)
        thread {
            val data = ArrayList<MediaModel>()
            val projection = arrayOf(MediaColumn.path, MediaColumn.size, MediaColumn.duration)
            val selection = if (mimeType.isEmpty()) null else getSelection(mimeType)
            val cursor = context.contentResolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection,
                selection, mimeType.toTypedArray(), orderBy
            ) ?: return@thread
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue
                // 时长
                val d = cursor.getLong(2)
                if (d <= 1000) continue
                // 数据
                val model = MediaModel()
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.duration = d
                model.durationTransform = transformTime(d)
                model.lastModifed = file.lastModified()
                model.type = MediaPickerConfig.TYPE_AUDIO
                data.add(model)
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(data) }
        }
    }

    @JvmStatic
    fun loadAudioJava(context: Context?, callback: (ArrayList<MediaModel>) -> Unit) {
        loadAudio(context, callback = callback)
    }

    @JvmStatic
    fun loadAudio(
        context: Context?,
        mimeType: ArrayList<String> = MediaMimeType.AUDIO_DEFAULT,
        minSize: Int = 1024,
        maxSize: Int = -1,
        folder: String = "",
        pageSize: Int = 24,
        pageIndex: Int = 0,
        orderBy: String = "${MediaColumn.dateModified} desc",
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        if (context == null) return
        if (mimeType.isEmpty()) mimeType.addAll(MediaMimeType.AUDIO_DEFAULT)
        thread {
            val data = ArrayList<MediaModel>()
            val projection = arrayOf(MediaColumn.path, MediaColumn.size, MediaColumn.duration)
            val cursor: Cursor?
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                val queryArgs = Bundle()
                queryArgs.putStringArray(
                    ContentResolver.QUERY_ARG_SORT_COLUMNS,
                    arrayOf(
                        orderBy.replace(" ", "")
                            .replace("desc", "")
                            .replace("asc", "")
                    )
                )
                if (orderBy.contains("desc")) {
                    queryArgs.putInt(
                        ContentResolver.QUERY_ARG_SORT_DIRECTION,
                        ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
                    )
                } else {
                    queryArgs.putInt(
                        ContentResolver.QUERY_ARG_SORT_DIRECTION,
                        ContentResolver.QUERY_SORT_DIRECTION_ASCENDING
                    )
                }
                queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, pageSize)
                queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, pageSize * pageIndex)
                if (mimeType.isNotEmpty())
                    queryArgs.putString(
                        ContentResolver.QUERY_ARG_SQL_SELECTION,
                        getSelectionValue(mimeType)
                    )
                cursor = context.contentResolver.query(
                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                    projection, queryArgs, null
                )
            } else {
                val selection = if (mimeType.isEmpty()) null else getSelection(mimeType)
                cursor = context.contentResolver.query(
                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection,
                    selection, mimeType.toTypedArray(),
                    "$orderBy limit $pageSize offset ${pageSize * pageIndex}"
                )
            }
            if (cursor == null) return@thread
            while (cursor.moveToNext()) {
                // 路径
                val path = cursor.getString(0)
                val file = File(path)
                if (!file.exists()) continue
                if (folder.isNotEmpty() && folder != file.parent) continue
                // 大小
                val size = cursor.getLong(1)
                if (size < minSize) continue
                if (maxSize != -1 && size > maxSize) continue
                // 时长
                val d = cursor.getLong(2)
                if (d <= 1000) continue
                // 数据
                val model = MediaModel()
                model.path = path
                model.name = file.name
                model.size = size
                model.sizeTransform = transformSize(size)
                model.duration = d
                model.durationTransform = transformTime(d)
                model.lastModifed = file.lastModified()
                model.type = MediaPickerConfig.TYPE_AUDIO
                data.add(model)
            }
            cursor.close()
            Handler(Looper.getMainLooper()).post { callback(data) }
        }
    }

    @JvmStatic
    fun loadAudioJava(
        context: Context?, pageSize: Int, pageIndex: Int,
        callback: (ArrayList<MediaModel>) -> Unit,
    ) {
        loadAudio(context, pageSize = pageSize, pageIndex = pageIndex, callback = callback)
    }

    /**
     * 查询类型
     */
    @JvmStatic
    fun loadMimeType(context: Context?, type: Int): HashSet<String> {
        if (context == null) return HashSet()

        val uri = when (type) {
            MediaPickerConfig.TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            MediaPickerConfig.TYPE_AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }
        val data = HashSet<String>()
        val cursor = context.contentResolver.query(
            uri, arrayOf(MediaColumn.mimeType, MediaColumn.path),
            null, null, null
        )
        if (cursor != null) {
            while (cursor.moveToNext()) {
                val mimeType = cursor.getString(0).toLowerCase(Locale.getDefault())
//                logD("${mimeType}_${cursor.getString(1)}")
                data.add(mimeType)
            }
            cursor.close()
        }
        data.forEach { logD(it) }
        return data
    }

    /**
     * 查询指定路径的媒体类型
     */
    fun findMimeType(context: Context?, type: Int, path: String): String {
        var voiceFormat = ""
        val dotIndex = path.lastIndexOf(".")
        if (path.isNotEmpty() && dotIndex >= 0 && path.length > dotIndex)
            voiceFormat = path.substring(dotIndex + 1)
        if (context == null) return voiceFormat
        val uri = when (type) {
            MediaPickerConfig.TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            MediaPickerConfig.TYPE_AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }
        val cursor = context.contentResolver.query(
            uri, arrayOf(MediaColumn.mimeType, MediaColumn.path),
            "${MediaColumn.path}=?", arrayOf(path), null
        )
        if (cursor != null && cursor.moveToNext()) {
            voiceFormat = cursor.getString(0).toLowerCase(Locale.getDefault())
            cursor.close()
        }
        return voiceFormat
    }

    /**
     * 转换大小为B\KB\MB\GB
     */
    @JvmStatic
    fun transformSize(size: Long): String {
        if (size <= 0) return "0B"

        when {
            size < 1024 -> return "${size}B"
            size < 1048576 -> {
                val transformSize = BigDecimal(size / 1024.0)
                    .setScale(2, BigDecimal.ROUND_HALF_UP).toDouble()
                return "${transformSize}KB"
            }

            size < 1073741824 -> {
                val transformSize = BigDecimal(size / 1048576.0)
                    .setScale(2, BigDecimal.ROUND_HALF_UP).toDouble()
                return "${transformSize}MB"
            }

            else -> {
                val transformSize = BigDecimal(size / 1073741824.0)
                    .setScale(2, BigDecimal.ROUND_HALF_UP).toDouble()
                return "${transformSize}GB"
            }
        }
    }

    /**
     * 获取图片宽高
     */
    @JvmStatic
    fun getImageSize(path: String): Size {
        try {
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeFile(path, options)
            options.outWidth
            val orientation = ExifInterface(path)
                .getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
            return if (
                orientation == ExifInterface.ORIENTATION_ROTATE_90 ||
                orientation == ExifInterface.ORIENTATION_ROTATE_270
            ) {
                Size(options.outHeight, options.outWidth)
            } else {
                Size(options.outWidth, options.outHeight)
            }
        } catch (e: Exception) {
            logD("获取图片宽高异常")
        }
        return Size(0, 0)
    }

    /**
     * 获取视频宽高
     */
    @JvmStatic
    fun getVideoSize(path: String): Size {
        val retriever = MediaMetadataRetriever()
        retriever.setDataSource(path)
        val w = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)
        val h = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)
        var width = 0
        var height = 0
        try {
            width = if (w.isNullOrEmpty()) 0 else w.toInt()
            height = if (h.isNullOrEmpty()) 0 else h.toInt()
        } catch (e: Exception) {
            logD("获取视频宽高异常")
        }
        return Size(width, height)
    }

    /**
     * 检测视频是否存在音频
     * 1: 有音频  0：无音频 -1 ：出错了
     */
    @JvmStatic
    fun hasAudio(path: String): Int {
        return if (TextUtils.isEmpty(path)) {
            -1
        } else try {
            val retriever = MediaMetadataRetriever()
            retriever.setDataSource(path)
            val hasAudio = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO)
            if (TextUtils.equals(hasAudio, "yes")) {
                1
            } else 0
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            -1
        }
    }

    /**
     * 获取媒体时长
     */
    @JvmStatic
    fun getMediaDuration(path: String): Long {
        val retriever = MediaMetadataRetriever()
        retriever.setDataSource(path)
        val d = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
        var duration = 0L
        try {
            duration = if (d.isNullOrEmpty()) 0L else d.toLong()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return duration
    }

    /**
     * 转换时间为00:01\01:00:00
     */
    @JvmStatic
    fun transformTime(d: Long, needHour: Boolean = false): String {
        return if (d <= 3600000 && !needHour) {
            val m = d / 1000 / 60
            val s = d / 1000 % 60
            String.format(Locale.CHINA, "%02d:%02d", m, s)
        } else {
            val h = d / 1000 / 60 / 60
            val m = d / 1000 / 60 % 60
            val s = d / 1000 % 60
            String.format(Locale.CHINA, "%02d:%02d:%02d", h, m, s)
        }
    }

    @JvmStatic
    fun transformTimeJava(d: Long): String = transformTime(d)

    /**
     * 删除图片
     */
    @JvmStatic
    fun deleteImage(context: Context?, imagePath: String?) {
        delete(MediaPickerConfig.TYPE_IMAGE, context, imagePath)
    }

    /**
     * 删除视频
     */
    @JvmStatic
    fun deleteVideo(context: Context?, videoPath: String?) {
        delete(MediaPickerConfig.TYPE_VIDEO, context, videoPath)
    }

    /**
     * 删除音频
     */
    @JvmStatic
    fun deleteAudio(context: Context?, audioPath: String?) {
        delete(MediaPickerConfig.TYPE_AUDIO, context, audioPath)
    }

    private fun delete(type: Int, context: Context?, deletePath: String?) {
        if (context == null || deletePath.isNullOrEmpty()) return

        val uri = when (type) {
            MediaPickerConfig.TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            MediaPickerConfig.TYPE_AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }
        context.contentResolver.delete(uri, "${MediaColumn.path}=?", arrayOf(deletePath))
    }

    /**
     * 修改图片名称
     */
    @JvmStatic
    fun updateImageName(context: Context?, oldPath: String?, newPath: String?) {
        updateName(MediaPickerConfig.TYPE_IMAGE, context, oldPath, newPath)
    }

    /**
     * 修改视频名称
     */
    @JvmStatic
    fun updateVideoName(context: Context?, oldPath: String?, newPath: String?) {
        updateName(MediaPickerConfig.TYPE_VIDEO, context, oldPath, newPath)
    }

    /**
     * 修改音频名称
     */
    @JvmStatic
    fun updateAudioName(context: Context?, oldPath: String?, newPath: String?) {
        updateName(MediaPickerConfig.TYPE_AUDIO, context, oldPath, newPath)
    }

    /**
     * 修改媒体名称
     */
    private fun updateName(type: Int, context: Context?, oldPath: String?, newPath: String?) {
        if (context == null || oldPath.isNullOrEmpty() || newPath.isNullOrEmpty()) return
        if (oldPath == newPath) return

        val uri = when (type) {
            MediaPickerConfig.TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            MediaPickerConfig.TYPE_AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
            else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }
        val contentValues = ContentValues()
        contentValues.put(MediaColumn.path, newPath)
        context.contentResolver.update(
            uri, contentValues, "${MediaColumn.path}=?", arrayOf(oldPath)
        )
        // 避免修改没有刷新媒体库，再刷新一遍
        refreshSystemMedia(context, newPath)
    }

    /**
     * 获取图片 uri
     */
    @JvmStatic
    fun findImageUriByPath(context: Context?, mediaPath: String?) =
        findUriByPath(context, MediaPickerConfig.TYPE_IMAGE, mediaPath)

    /**
     * 获取视频 uri
     */
    @JvmStatic
    fun findVideoUriByPath(context: Context?, mediaPath: String?) =
        findUriByPath(context, MediaPickerConfig.TYPE_VIDEO, mediaPath)

    /**
     * 获取音频 uri
     */
    @JvmStatic
    fun findAudioUriByPath(context: Context?, mediaPath: String?) =
        findUriByPath(context, MediaPickerConfig.TYPE_AUDIO, mediaPath)

    /**
     * 获取媒体 uri
     */
    private fun findUriByPath(context: Context?, type: Int, mediaPath: String?): Uri? {
        var resultUri: Uri? = null
        if (context == null || mediaPath.isNullOrEmpty()) return null
        try {
            val uri = when (type) {
                MediaPickerConfig.TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                MediaPickerConfig.TYPE_AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            }
            val cursor = context.contentResolver.query(
                uri, arrayOf(MediaColumn.id), "${MediaColumn.path}=? ",
                arrayOf(mediaPath), null
            )
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    val id = cursor.getInt(0)
                    resultUri = Uri.withAppendedPath(uri, "$id")
                }
                cursor.close()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return resultUri
    }

    /**
     * 根据本地文件获取MediaModel对象
     */
    @JvmStatic
    fun getAudioFromFile(
        context: Context, filePath: String, minSize: Int = 1024,
        maxSize: Int = -1, callback: (MediaModel) -> Unit,
    ) {
        val projection = arrayOf(
            MediaStore.Files.FileColumns.DATA,
            MediaStore.Files.FileColumns.SIZE,
            MediaStore.Files.FileColumns.DURATION
        )
        thread {
            // 数据
            val model = MediaModel()
            context.contentResolver.query(
                MediaStore.Files.getContentUri("external"),
                projection,
                MediaStore.Files.FileColumns.DATA + "=?",
                arrayOf<String>(filePath),
                null
            ).use { cursor ->
                if (cursor != null && cursor.moveToFirst()) {
                    val dataColumn = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)
                    val sizeColumn = cursor.getColumnIndex(MediaStore.Files.FileColumns.SIZE)
                    val durationColumn = cursor.getColumnIndex(MediaStore.Files.FileColumns.DURATION)

                    // 路径
                    val path = cursor.getString(dataColumn)
                    val file = File(path)
                    if (!file.exists()) return@thread
//                    // 大小
                    val size = cursor.getLong(sizeColumn)
                    if (size < minSize) return@thread
                    if (maxSize != -1 && size > maxSize) return@thread
                    // 时长
                    val duration = cursor.getLong(durationColumn)
                    if (duration <= 1000) return@thread

                    model.path = path
                    model.name = file.name
                    model.size = size
                    model.sizeTransform = transformSize(size)
                    model.duration = duration
                    model.durationTransform = transformTime(duration)
                    model.lastModifed = file.lastModified()
                    model.type = MediaPickerConfig.TYPE_AUDIO
                }
                cursor?.close()
                Handler(Looper.getMainLooper()).post { callback(model) }
            }
        }
    }

    /**
     * 刷新系统媒体库
     */
    @JvmStatic
    fun refreshSystemMedia(context: Context?, mediaPath: String?) {
        if (context == null || mediaPath.isNullOrEmpty()) return

        val file = File(mediaPath)
        if (!file.exists()) return

        MediaScannerConnection.scanFile(
            context, arrayOf(file.toString()), arrayOf(file.name), null
        )
    }

    private fun logD(msg: String) {
        Log.d(tag, msg)
    }
}